package com.example.playnote.net

import com.example.playnote.bean.Constant
import com.example.playnote.retrofit.ApiService
import com.example.playnote.utils.MMKVUtils
import com.google.gson.GsonBuilder
import me.hgj.jetpackmvvm.network.BaseNetworkApi
import me.hgj.jetpackmvvm.network.CoroutineCallAdapterFactory
import me.hgj.jetpackmvvm.network.interceptor.logging.LogInterceptor
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit

class NetworkApi : BaseNetworkApi() {
    companion object {
        private const val SAVE_USER_LOGIN_KEY = "user/login"
        private const val SAVE_USER_REGISTER_KEY = "user/register"
        private const val SET_COOKIE_KEY = "set-cookie"
        private const val COOKIE_NAME = "Cookie"
        private val instance: NetworkApi by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { NetworkApi() }

        //双重校验锁式-单例 封装NetApiService 方便直接快速调用
        val service: ApiService by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            instance.getApi(ApiService::class.java, Constant.BASE_URL)
        }
    }

    /**
     * 实现重写父类的setHttpClientBuilder方法，
     * 在这里可以添加拦截器，可以对 OkHttpClient.Builder 做任意你想要做的骚操作
     */
    override fun setHttpClientBuilder(builder: OkHttpClient.Builder): OkHttpClient.Builder {
        builder.apply {
            // get response cookie
            addInterceptor(GetCookieInterceptor())
            // set response cookie
            addInterceptor(SetCookieInterceptor())
            // 日志拦截器
            addInterceptor(LogInterceptor())
            //超时时间 连接、读、写
            connectTimeout(10, TimeUnit.SECONDS)
            readTimeout(5, TimeUnit.SECONDS)
            writeTimeout(5, TimeUnit.SECONDS)
        }
        return builder
    }

    class SetCookieInterceptor : Interceptor {
        override fun intercept(chain: Interceptor.Chain): Response {
            val request = chain.request()
            val builder = request.newBuilder()
            var domain = request.url.host
            if (domain.isNotEmpty()) {
                domain = MMKVUtils.getString(domain).toString()
                val cookie: String = domain.ifEmpty { "" }
                if (cookie.isNotEmpty()) {
                    builder.addHeader(COOKIE_NAME, cookie)
                }
            }
            return chain.proceed(builder.build())
        }

    }

    class GetCookieInterceptor : Interceptor {
        override fun intercept(chain: Interceptor.Chain): Response {
            val request = chain.request()
            val response = chain.proceed(request)
            val requestUrl = request.url.toString()
            val domain = request.url.host
            if ((requestUrl.contains(SAVE_USER_LOGIN_KEY) || requestUrl.contains(
                    SAVE_USER_REGISTER_KEY
                )) && response.headers(SET_COOKIE_KEY).isNotEmpty()
            ) {
                val cookies = response.headers(SET_COOKIE_KEY)
                val cookie = encodeCookie(cookies)
                saveCookie(requestUrl, domain, cookie)
            }
            return response
        }

        private fun saveCookie(url: String, domain: String, cookies: String) {
            url ?: return // 如果 url 为 null，则直接返回
            domain ?: return // 如果 domain 为 null，则直接返回
            MMKVUtils.put(url, cookies)
            MMKVUtils.put(domain, cookies)
        }

        /**
         * save cookie string
         */
        private fun encodeCookie(cookies: List<String>): String {
            val sb = StringBuilder()
            val set = HashSet<String>()
            cookies
                .map { cookie ->
                    cookie.split(";".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                }
                .forEach {
                    it.filterNot { set.contains(it) }.forEach { set.add(it) }
                }

            val ite = set.iterator()
            while (ite.hasNext()) {
                val cookie = ite.next()
                sb.append(cookie).append(";")
            }

            val last = sb.lastIndexOf(";")
            if (sb.length - 1 == last) {
                sb.deleteCharAt(last)
            }

            return sb.toString()
        }
    }

    /**
     * 实现重写父类的setRetrofitBuilder方法，
     * 在这里可以对Retrofit.Builder做任意骚操作，比如添加GSON解析器，protobuf等
     */
    override fun setRetrofitBuilder(builder: Retrofit.Builder): Retrofit.Builder {
        return builder.apply {
            addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
            addCallAdapterFactory(CoroutineCallAdapterFactory())
        }
    }
}